<template>
  <div class="lineage-graph" ref="containerRef">
    <svg :width="svgWidth" :height="svgHeight" @wheel="handleWheel" @mousedown="handleMouseDown">
      <!-- 背景网格 -->
      <defs>
        <pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
          <path d="M 20 0 L 0 0 0 20" fill="none" stroke="#e0e0e0" stroke-width="1"/>
        </pattern>
        <!-- 箭头标记 -->
        <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
          <polygon points="0 0, 10 3.5, 0 7" fill="#409eff"/>
        </marker>
      </defs>
      
      <!-- 网格背景 -->
      <rect width="100%" height="100%" fill="url(#grid)"/>
      
      <!-- 变换组 -->
      <g :transform="`translate(${transform.x}, ${transform.y}) scale(${transform.scale})`">
        <!-- 连接线 -->
        <g class="edges">
          <path
            v-for="edge in computedEdges"
            :key="`${edge.source}-${edge.target}`"
            :d="edge.path"
            :stroke="getEdgeColor(edge.type)"
            stroke-width="2"
            fill="none"
            marker-end="url(#arrowhead)"
            class="edge"
            @click="handleEdgeClick(edge)"
          />
        </g>
        
        <!-- 表节点 -->
        <g class="nodes">
          <g
            v-for="table in tables"
            :key="table.id"
            :transform="`translate(${table.x}, ${table.y})`"
            class="table-node"
            @click="handleTableClick(table)"
            @mouseover="handleTableHover(table)"
            @mouseout="handleTableOut(table)"
          >
            <!-- 表背景 -->
            <rect
              width="140"
              height="80"
              rx="8"
              :fill="getTableColor(table.type)"
              :stroke="getTableStrokeColor(table.type)"
              stroke-width="2"
              class="table-bg"
            />
            
            <!-- 表名 -->
            <text
              x="70"
              y="25"
              text-anchor="middle"
              font-size="14"
              font-weight="600"
              fill="white"
            >
              {{ table.name }}
            </text>
            
            <!-- 表类型 -->
            <text
              x="70"
              y="42"
              text-anchor="middle"
              font-size="11"
              fill="rgba(255,255,255,0.8)"
            >
              {{ getTableTypeLabel(table.type) }}
            </text>
            
            <!-- 统计信息 -->
            <text
              x="70"
              y="58"
              text-anchor="middle"
              font-size="10"
              fill="rgba(255,255,255,0.7)"
            >
              {{ formatRowCount(table.rowCount) }} 行
            </text>
            
            <!-- 连接点 -->
            <circle cx="0" cy="40" r="4" fill="#fff" stroke="#409eff" stroke-width="2" class="connect-point left"/>
            <circle cx="140" cy="40" r="4" fill="#fff" stroke="#409eff" stroke-width="2" class="connect-point right"/>
          </g>
        </g>
      </g>
    </svg>
    
    <!-- 工具栏 -->
    <div class="graph-tools">
      <el-button-group>
        <el-button size="small" @click="zoomIn">
          <el-icon><ZoomIn /></el-icon>
        </el-button>
        <el-button size="small" @click="zoomOut">
          <el-icon><ZoomOut /></el-icon>
        </el-button>
        <el-button size="small" @click="resetZoom">
          <el-icon><RefreshLeft /></el-icon>
        </el-button>
      </el-button-group>
    </div>
    
    <!-- 小地图 -->
    <div class="minimap">
      <svg width="200" height="120" viewBox="0 0 800 600">
        <rect width="800" height="600" fill="#f8f9fa" stroke="#ddd" stroke-width="1"/>
        <g v-for="table in tables" :key="table.id">
          <rect
            :x="table.x * 0.2"
            :y="table.y * 0.2"
            width="28"
            height="16"
            :fill="getTableColor(table.type)"
            opacity="0.7"
          />
        </g>
        <!-- 视窗指示器 -->
        <rect
          :x="-transform.x * 0.2"
          :y="-transform.y * 0.2"
          :width="svgWidth * 0.2 / transform.scale"
          :height="svgHeight * 0.2 / transform.scale"
          fill="none"
          stroke="#409eff"
          stroke-width="2"
          opacity="0.6"
        />
      </svg>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  tables: {
    type: Array,
    default: () => []
  },
  lineages: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['table-click', 'table-hover', 'edge-click'])

const containerRef = ref(null)
const svgWidth = ref(800)
const svgHeight = ref(600)

// 变换状态
const transform = ref({
  x: 0,
  y: 0,
  scale: 1
})

// 拖拽状态
const dragState = ref({
  isDragging: false,
  startX: 0,
  startY: 0,
  startTransformX: 0,
  startTransformY: 0
})

// 计算连接线路径
const computedEdges = computed(() => {
  return props.lineages.map(lineage => {
    const sourceTable = props.tables.find(t => t.id === lineage.source)
    const targetTable = props.tables.find(t => t.id === lineage.target)
    
    if (!sourceTable || !targetTable) return null
    
    const startX = sourceTable.x + 140
    const startY = sourceTable.y + 40
    const endX = targetTable.x
    const endY = targetTable.y + 40
    
    // 计算贝塞尔曲线控制点
    const controlX1 = startX + 60
    const controlY1 = startY
    const controlX2 = endX - 60
    const controlY2 = endY
    
    const path = `M ${startX} ${startY} C ${controlX1} ${controlY1}, ${controlX2} ${controlY2}, ${endX} ${endY}`
    
    return {
      ...lineage,
      path,
      startX,
      startY,
      endX,
      endY
    }
  }).filter(Boolean)
})

// 事件处理
const handleTableClick = (table) => {
  emit('table-click', table)
}

const handleTableHover = (table) => {
  emit('table-hover', table)
}

const handleTableOut = (table) => {
  // 鼠标离开事件
}

const handleEdgeClick = (edge) => {
  emit('edge-click', edge)
}

const handleWheel = (event) => {
  event.preventDefault()
  const delta = event.deltaY > 0 ? 0.9 : 1.1
  const newScale = Math.max(0.1, Math.min(3, transform.value.scale * delta))
  
  // 以鼠标位置为中心缩放
  const rect = containerRef.value.getBoundingClientRect()
  const mouseX = event.clientX - rect.left
  const mouseY = event.clientY - rect.top
  
  const scaleDiff = newScale - transform.value.scale
  transform.value.x -= (mouseX - transform.value.x) * scaleDiff / transform.value.scale
  transform.value.y -= (mouseY - transform.value.y) * scaleDiff / transform.value.scale
  transform.value.scale = newScale
}

const handleMouseDown = (event) => {
  if (event.button === 0) { // 左键
    dragState.value.isDragging = true
    dragState.value.startX = event.clientX
    dragState.value.startY = event.clientY
    dragState.value.startTransformX = transform.value.x
    dragState.value.startTransformY = transform.value.y
    
    document.addEventListener('mousemove', handleMouseMove)
    document.addEventListener('mouseup', handleMouseUp)
  }
}

const handleMouseMove = (event) => {
  if (dragState.value.isDragging) {
    const deltaX = event.clientX - dragState.value.startX
    const deltaY = event.clientY - dragState.value.startY
    
    transform.value.x = dragState.value.startTransformX + deltaX
    transform.value.y = dragState.value.startTransformY + deltaY
  }
}

const handleMouseUp = () => {
  dragState.value.isDragging = false
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
}

// 缩放控制
const zoomIn = () => {
  transform.value.scale = Math.min(3, transform.value.scale * 1.2)
}

const zoomOut = () => {
  transform.value.scale = Math.max(0.1, transform.value.scale * 0.8)
}

const resetZoom = () => {
  transform.value.scale = 1
  transform.value.x = 0
  transform.value.y = 0
}

// 调整画布大小
const resizeCanvas = () => {
  if (containerRef.value) {
    const rect = containerRef.value.getBoundingClientRect()
    svgWidth.value = rect.width
    svgHeight.value = rect.height
  }
}

// 工具方法
const getTableColor = (type) => {
  const colors = {
    'fact': '#409eff',
    'dim': '#67c23a',
    'ods': '#e6a23c',
    'dws': '#909399'
  }
  return colors[type] || '#909399'
}

const getTableStrokeColor = (type) => {
  const colors = {
    'fact': '#337ecc',
    'dim': '#529b2e',
    'ods': '#b88230',
    'dws': '#73767a'
  }
  return colors[type] || '#73767a'
}

const getTableTypeLabel = (type) => {
  const labels = {
    'fact': '事实表',
    'dim': '维度表',
    'ods': '贴源表',
    'dws': '汇总表'
  }
  return labels[type] || type
}

const getEdgeColor = (type) => {
  const colors = {
    'etl': '#409eff',
    'join': '#67c23a',
    'aggregate': '#e6a23c'
  }
  return colors[type] || '#409eff'
}

const formatRowCount = (count) => {
  if (!count) return '0'
  if (count >= 1000000) {
    return (count / 1000000).toFixed(1) + 'M'
  }
  if (count >= 1000) {
    return (count / 1000).toFixed(1) + 'K'
  }
  return count.toString()
}

// 生命周期
onMounted(() => {
  resizeCanvas()
  window.addEventListener('resize', resizeCanvas)
})

onUnmounted(() => {
  window.removeEventListener('resize', resizeCanvas)
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
})
</script>

<style scoped>
.lineage-graph {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.lineage-graph svg {
  cursor: grab;
}

.lineage-graph svg:active {
  cursor: grabbing;
}

.table-node {
  cursor: pointer;
  transition: transform 0.2s;
}

.table-node:hover {
  transform: scale(1.05);
}

.table-bg {
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
}

.connect-point {
  opacity: 0;
  transition: opacity 0.2s;
}

.table-node:hover .connect-point {
  opacity: 1;
}

.edge {
  cursor: pointer;
  transition: stroke-width 0.2s;
}

.edge:hover {
  stroke-width: 4;
}

.graph-tools {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 10;
}

.minimap {
  position: absolute;
  bottom: 16px;
  right: 16px;
  background: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 8px;
  z-index: 10;
}

.minimap svg {
  display: block;
}
</style> 